Skip to content

fix(landing): repair Lighthouse-flagged CWV audits on production#5605

Merged
waleedlatif1 merged 6 commits into
stagingfrom
perf-audit-fixes
Jul 12, 2026
Merged

fix(landing): repair Lighthouse-flagged CWV audits on production#5605
waleedlatif1 merged 6 commits into
stagingfrom
perf-audit-fixes

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

Ran a full Lighthouse audit against live production (www.sim.ai) and empirically triaged every audit the user's lighthouse-metrics.com scan flagged — confirming which were genuinely failing vs. already passing before touching anything.

Fixed:

  • lcp-discovery-insightpriority on next/image generates a preload <link> but Next does not auto-add fetchpriority=high to it (confirmed via raw deployed HTML). Added explicit fetchPriority='high' to all 5 priority Image usages across hero, enterprise, and blog/library post/index cards.
  • valid-source-maps — production ships zero source maps (productionBrowserSourceMaps defaults false). Enabled it — safe since this repo's frontend is already fully open source.
  • image-delivery-insight (55.8KB wasted) — feature-integrate-ui.png's sizes hint was a flat 1050px regardless of viewport, so mobile fetched the 1920w variant for a ~423px real render. Replaced with a responsive expression derived from the sibling backdrop image's own correct hint, scaled by the documented 125% overhang.
  • cache-insight (our controllable portion) — _next/static/* (content-hashed, immutable per deploy) shared one cache rule with unhashed /public assets, capping both at 1-day. Split into two rules; hashed assets now get 1-year immutable. Verified via a real build + running server that both paths return the correct distinct header.

Investigated, not changed (documented why, not assumed):

  • legacy-javascript-insight (14KB) — traced via a temporary source-map build to next/dist/build/polyfills/polyfill-module.js, Next's own built-in polyfill bundle. Not our code, not a dependency, no browserslist misconfiguration on our end.
  • forced-reflow-insight — even with source maps present, the dominant cost (335-417ms) stayed [unattributed] by Chrome's own profiler; the small attributed slice bounced non-deterministically between our chunk and a third-party script across runs. Not a confident single root cause.
  • render-blocking-insight / network-dependency-tree-insight / bf-cache — bf-cache's actual failure reason is Cache-Control: no-store on the main document, the exact root cause already fixed on staging in fix(landing): fix Core Web Vitals regressions across public marketing pages #5522/fix(landing): revert unoptimized removal, compress source images instead #5528 (the PublicEnvScript/unstable_noStore fix), just not yet promoted to main/prod.

Type of Change

  • Bug fix / performance fix

Testing

  • tsc --noEmit clean (one pre-existing, unrelated error in providers/meta/index.ts)
  • bun run lint clean
  • Full production build + running server: verified the two new cache-control rules empirically return the correct header on a hashed _next/static CSS/font asset vs. an unhashed /public SVG
  • Caught and fixed a real regex-parsing bug in the new cache-control headers via the build itself (Next's route-source parser requires the whole pattern wrapped in one outer paren)

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Empirically verified against a live full Lighthouse run of www.sim.ai
(production, pre-fix) plus a local build of the exact deployed commit with
source maps temporarily enabled for root-causing. Distinguished genuinely
failing audits from passing ones already misread as broken.

- fetchPriority missing on every LCP hero image: `priority` generates a
  preload <link> but Next does not auto-add fetchpriority=high to it -
  confirmed via raw deployed HTML diff. Added explicit fetchPriority='high'
  to all 5 priority Image usages (hero, enterprise, blog/library post +
  index cards).
- valid-source-maps failing: production ships no source maps at all
  (productionBrowserSourceMaps defaults false). Enabled it - safe here since
  this repo's frontend is already fully open source, so no incremental
  exposure versus Next's default.
- image-delivery-insight (55.8KB wasted): feature-integrate-ui.png's `sizes`
  hint was a flat 1050px regardless of viewport, so mobile fetched the
  1920w variant for a ~423px real render. Replaced with a responsive sizes
  expression derived from the sibling backdrop image's own (already
  correct) hint, scaled by the callout's documented 125% overhang.
- cache-insight (best-fixable portion): _next/static/* filenames are
  content-hashed and immutable per deploy, but shared one cache rule with
  unhashed /public assets, capping both at 1-day max-age. Split into two
  rules - hashed assets now get 1-year immutable, unhashed assets keep the
  shorter revalidating TTL. Verified via a real build + server that both
  paths now return the correct distinct header.

Investigated and NOT changed (documented, not assumed):
- legacy-javascript-insight (14KB): traced via sourcemap to
  next/dist/build/polyfills/polyfill-module.js - Next's own built-in
  polyfill bundle, not our code or a dependency, and not exposed via any
  next.config.ts option. No browserslist misconfiguration on our end (none
  exists; Next already defaults to its modern target).
- forced-reflow-insight: even with source maps present locally, the
  dominant cost (335-417ms) stayed [unattributed] by Chrome's own profiler,
  and the small attributed slice was non-deterministic between our own
  chunk and a third-party script (HubSpot analytics) across runs - not a
  confident single root cause worth a targeted fix.
- render-blocking-insight / network-dependency-tree / bf-cache: bf-cache's
  actual failure reason is Cache-Control: no-store on the main document -
  the exact root cause already fixed on staging (PR #5522/#5528, the
  PublicEnvScript/unstable_noStore fix) but not yet promoted to main/prod.
  Resolves once that ships, not additional work here.
@vercel

vercel Bot commented Jul 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Jul 12, 2026 12:51am

Request Review

@cursor

cursor Bot commented Jul 11, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Landing performance and cache-header changes are low risk; enabling browser source maps is intentional for an already public frontend and is paired with noindex/TTL bounds on .map files.

Overview
Targets production Lighthouse failures around LCP, image delivery, source maps, and caching, with smaller llms.txt and blog asset tweaks.

Core Web Vitals / performance: Adds explicit fetchPriority='high' on priority next/image instances (hero backdrop, enterprise hero, blog index first card, post cover) so preloaded LCP images get high fetch priority. Replaces the flat 1050px sizes on the integrations callout image with a responsive expression so mobile does not over-fetch. Enables productionBrowserSourceMaps: true in next.config.ts for valid-source-maps audits (repo is already public).

Caching: Excludes _next/static/ from the 1-day cache rule applied to unhashed /public static files so hashed build assets keep Next’s long immutable TTL. Fixes the .map header matcher (removed erroneous trailing $), adds short Cache-Control on .map responses, and keeps x-robots-tag: noindex.

LLM / docs manifests: Dynamic docs and sim llms.txt routes now emit markdown links; static public/llms.txt copies are removed. llms-full.txt copy updates (Chat naming, Next.js 16) and link formatting. Mothership blog ogImage switches from .png to .jpg.

Reviewed by Cursor Bugbot for commit a501857. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes several Lighthouse and landing-page performance issues. The main changes are:

  • Adds explicit high fetch priority to priority landing and content images.
  • Updates the integrations callout image sizing hint.
  • Enables production browser source maps.
  • Splits cache headers for public assets, hashed static assets, and source maps.
  • Updates LLM text routes and removes stale static llms.txt files.
  • Replaces the Mothership blog cover PNG reference with a JPG asset.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
apps/sim/app/(landing)/components/features/components/integrations-callout/integrations-callout.tsx Updates the callout image sizes expression to better match the responsive layout.
apps/sim/next.config.ts Enables production source maps and updates cache-control headers for public assets and source maps.
apps/sim/app/(landing)/components/content-index-page/content-index-page.tsx Adds explicit fetch priority to the first priority image in content index cards.
apps/sim/app/(landing)/components/content-post-page/content-post-page.tsx Adds explicit high fetch priority to the content post hero image.
apps/sim/app/(landing)/components/hero/hero.tsx Adds explicit high fetch priority to the landing hero image.
apps/sim/app/(landing)/enterprise/enterprise.tsx Adds explicit high fetch priority to the enterprise hero image.
apps/sim/content/blog/mothership/index.mdx Updates the Mothership blog Open Graph image path from PNG to JPG.
apps/sim/app/llms-full.txt/route.ts Refreshes LLM-facing product copy and link formatting.
apps/docs/app/llms.txt/route.ts Updates generated docs LLM text to use markdown links.

Reviews (3): Last reviewed commit: "fix(llms): actually include the route.ts..." | Re-trigger Greptile

Comment thread apps/sim/next.config.ts
…6s -> 2.8s)

Ran a full Lighthouse sweep across every public page as requested. /blog
scored 73 (LCP 6.6s) while every other page scored 95+ - reproduced
consistently across 3 runs, not noise. Traced via lcp-breakdown-insight:
the LCP image (mothership/cover.png, 241KB even after the earlier palette
compression pass) took 6+ seconds to download on simulated mobile
throttling, well beyond what its size should cost.

PNG is a poor fit for this illustration's subtle gradients versus JPEG's
lossy compression. Verified empirically before converting: same 1920x1080
resolution, visually identical (spot-checked), 241KB -> 65KB (73% smaller).
No other cover in the content set uses PNG and benefits the same way
(checked copilot/cover.png, the only other PNG cover - already optimal at
64KB, converting it yielded no improvement, left unchanged).

Verified fix: /blog score 73->93, LCP 6.6s->2.8s, reproduced across 3 runs.
- integrations-callout: account for FeatureCard's max-lg:grid-cols-1 mobile
  stack in the sizes hint, verified against Lighthouse's measured mobile
  render width.
- next.config: remove a custom _next/static cache-control rule that never
  actually fired (confirmed via header-marker test) - Next's own built-in
  default already applies the correct immutable 1yr cache to that path.
- integrations-callout: derive sizes from the section's actual grid math
  (fixed 386px copy column, 40px gap, section gutters) instead of an
  approximated vw fraction. Verified against a static reproduction of the
  layout rendered at each Tailwind breakpoint - the old 110vw mobile tier
  underestimated real render width by ~3% right at the 1023px stack
  boundary, which could cause the browser to pick a too-small srcset
  candidate and upscale.
- next.config: the .map header rule's trailing `$` was read as a literal
  character by Next's path-to-regexp source matcher, not a regex anchor,
  so the rule never matched a real .map URL (confirmed via routes-manifest
  regex + a live header check). Removed the dead anchor and added a
  bounded Cache-Control so a future decision to stop shipping source maps
  isn't undermined by a 1yr immutable cache on already-fetched maps.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit f7e3b36. Configure here.

…c files

Both the marketing site and docs site's llms.txt validator errors ("does
not appear to contain any links") traced to the same root cause: a static
public/llms.txt shadowed a better-written, already-existing dynamic
app/llms.txt route, and every "link" in the static files (and in the
docs app's auto-generated route) was bare `label: url` text, not Markdown
link syntax - so a strict Markdown-link parser found zero matches even
though URLs were visibly present.

- apps/sim: delete public/llms.txt (dead code, shadowing the properly
  Markdown-linked app/llms.txt route.ts, confirmed via production headers
  showing the static file was what actually served). Fix llms-full.txt's
  Links/Support/Legal sections to use [label](url) syntax, correct a
  stale "Next.js 15" reference, and replace "Mothership" with "Chat" per
  the constitution's language rules.
- apps/docs: same shadowing issue - delete the orphaned public/llms.txt
  (also still said "Mothership"). Fix the auto-generated per-page link
  list in app/llms.txt/route.ts to emit [title](url) instead of
  "title: url" for every documentation page.
The prior commit (3b2d35c) only staged the two deleted public/llms.txt
files - these two modified route.ts files (the Mothership/link-format
fixes they were meant to accompany) were left unstaged. No new changes,
just completing that commit's intent.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit a501857. Configure here.

@waleedlatif1 waleedlatif1 merged commit fcf4e02 into staging Jul 12, 2026
12 of 13 checks passed
@waleedlatif1 waleedlatif1 deleted the perf-audit-fixes branch July 12, 2026 00:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant